package com.teamwings.ctrls.formCtrls.noField;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.teamwings.common.aspect.annotation.FormControl;
import com.teamwings.common.constant.FormConstant;
import com.teamwings.common.exception.ResultException;
import com.teamwings.common.jsqlparser.SelectParseHelper;
import com.teamwings.common.vo.Result;
import com.teamwings.ctrls.FormComponent;
import com.teamwings.modules.design.vo.FormVo;
import com.teamwings.modules.page.service.IPageService;
import com.teamwings.util.FieldsLoopUtil;
import com.teamwings.util.VoUtils;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.jeecgframework.poi.excel.ExcelExportUtil;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.*;

@EqualsAndHashCode(callSuper = true)
@FormControl(type = "export_button", needField = false)
@Data
public class ExportButton extends FormComponent {

    public ExportButton() {
        super();
        this.type = "export_button";
    }

    @Override
    public Result<?> trigger(
            FormConstant.TRIGGER_TYPE type,
            IPageService pageService,
            FormVo formDesignCode,
            Object paramsData
    ) {
        JSONObject jo = JSON.parseObject(paramsData + "");
        // 导出所有方法
        if (type == FormConstant.TRIGGER_TYPE.CTRL_HANDLER) {
            String key = jo.getString("key");
            String formId = jo.getString("formId");
            // 前端传递过来的字段模板
            JSONArray columnsTemplate = jo.getJSONArray("columns");
            // key字段名称【用于选中导出】
            String rowKey = jo.getString("rowKey");
            // 选中的key数组【用于选中导出】
            JSONArray selectedRowKeys = jo.getJSONArray("selectedRowKeys");
            // 找到逻辑表格
            FormComponent logicTable = this.getComponent(pageService, key, formId);
            // 查询要导出的数据
            List<Map<String, Object>> data = this.getData(logicTable, pageService, rowKey, selectedRowKeys);
            // 获取逻辑表格的label名称
            String name = this.getLogicTableName(logicTable);
            // 获取字段名和列名的map关系
            Map<String, String> columnTitleMap = this.generateColumns(columnsTemplate, logicTable);
            // 生成jeecgboot workbook对象
            Workbook workbook = this.generateExcel(name, columnTitleMap, data);
            // 导出excel
            this.export(workbook, name);
            return Result.returnVoid();
        } else {
            return Result.error("参数有误，查询失败。");
        }
    }

    private void export(Workbook workbook, String name) {
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.setHeader("Content-Language", "zh-CN");
        response.setContentType("application/vnd.ms-excel");
        try {
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(name.getBytes("UTF-8"), "ISO8859-1") + ".xls");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            response.addHeader("Content-Disposition", "attachment;filename=" + name + ".xls");
        }
        OutputStream output = null;
        try {
            output = response.getOutputStream();
            workbook.write(output);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (output != null) {
                    output.flush();
                }
                if (output != null) {
                    output.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private String getLogicTableName(FormComponent logicTable) {
        return String.valueOf(logicTable.getLabel());
    }

    private FormComponent getComponent(IPageService pageService, String key, String formId) {
        // 根据formId找到表单设计
        String tableCode = pageService.getTableCodeByFormId(formId);
        FormVo formVo = VoUtils.newFormVoAllowNoField(tableCode);
        List<FormComponent> formComponentList = formVo.getList();

        List<FormComponent> components = FieldsLoopUtil.getComponents(formComponentList, (formComponent) -> formComponent.getKey().equals(key));
        if (components.size() == 0) {
            throw new ResultException("没找到相应的控件");
        }
        return components.get(0);
    }

    // 获取数据
    private List<Map<String, Object>> getData(
            FormComponent logicTable,
            IPageService pageService,
            String rowKey,
            JSONArray selectedRowKeys
    ) {
        List<Map<String, Object>> res = new ArrayList<>();
        List<Map> list = null;
        Map<String, Object> options = logicTable.getOptions();
        String tableType = String.valueOf(options.get("tableType"));
        String sql = String.valueOf(options.get("sql"));
        String tableName = String.valueOf(options.get("tableName"));
        QueryWrapper<Object> queryWrapper = new QueryWrapper<>();
        ArrayList<String> columns = new ArrayList<>();
        if (options.get("columns") instanceof JSONArray) {
            JSONArray columnsJSONArr = (JSONArray) options.get("columns");
            for (Object o : columnsJSONArr) {
                String column = String.valueOf(o);
                columns.add(column);
            }
        }

        ArrayList<String> keyList = new ArrayList<>();
        if (selectedRowKeys != null && selectedRowKeys.size() > 0) {
            for (int i = 0; i < selectedRowKeys.size(); i++) {
                keyList.add(selectedRowKeys.getString(i));
            }
        }

        if (tableType.equals(FormConstant.LOGIC_TABLE_TYPE.SQL.getText())) {
            // 直接查询
            if (StringUtils.isNotEmpty(rowKey)) {
                boolean hasWhere = SelectParseHelper.hasWhere(pageService, sql);
                if (keyList.size() > 0) {
                    queryWrapper.in(rowKey, keyList);
                }
                res = pageService.selectBySql(sql, queryWrapper, hasWhere);
            } else {
                list = pageService.executeSql(sql);
                for (Map map : list) {
                    res.add(new HashMap<String, Object>(map));
                }
            }
        } else if (tableType.equals(FormConstant.LOGIC_TABLE_TYPE.SINGLE_TABLE.getText())) {
            if (StringUtils.isNotEmpty(rowKey)) {
                queryWrapper.in(rowKey, keyList);
                res = pageService.selectAll(tableName, queryWrapper);
            } else {
                list = pageService.selectFields(StringUtils.join(columns, ","), tableName);
                for (Map map : list) {
                    res.add(new HashMap<String, Object>(map));
                }
            }
        } else {
            // 报错，提示逻辑表格未设置
        }

        return res;
    }

    // 获取数据
    private List<Map<String, Object>> getData(FormComponent logicTable, IPageService pageService) {
        List<Map> list = null;
        Map<String, Object> options = logicTable.getOptions();
        String tableType = String.valueOf(options.get("tableType"));
        String sql = String.valueOf(options.get("sql"));
        String tableName = String.valueOf(options.get("tableName"));
        ArrayList<String> columns = new ArrayList<>();
        if (options.get("columns") instanceof JSONArray) {
            JSONArray columnsJSONArr = (JSONArray) options.get("columns");
            for (Object o : columnsJSONArr) {
                String column = String.valueOf(o);
                columns.add(column);
            }
        }

        if (tableType.equals(FormConstant.LOGIC_TABLE_TYPE.SQL.getText())) {
            // 直接查询
            list = pageService.executeSql(sql);
        } else if (tableType.equals(FormConstant.LOGIC_TABLE_TYPE.SINGLE_TABLE.getText())) {
            list = pageService.selectFields(StringUtils.join(columns, ","), tableName);
        } else {
            // 报错，提示逻辑表格未设置
        }

        List<Map<String, Object>> res = new ArrayList<>();

        for (Map map : list) {
            res.add(new HashMap<String, Object>(map));
        }

        return res;
    }

    private Map<String, String> generateColumns(JSONArray columnsTemplate, FormComponent logicTable) {
        // 这里要使用linkedHashMap否则导出来的excel的列会乱掉
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        ArrayList<String> columns = new ArrayList<>();
        Map<String, Object> options = logicTable.getOptions();
        String tableType = String.valueOf(options.get("tableType"));

        if (options.get("columns") instanceof JSONArray) {
            JSONArray columnsJSONArr = (JSONArray) options.get("columns");
            for (Object o : columnsJSONArr) {
                String column = String.valueOf(o);
                if (tableType.equals(FormConstant.LOGIC_TABLE_TYPE.SQL.getText())) {
                    if (column.contains(".")) {
                        column = column.split("\\.")[1];
                    }
                }
                columns.add(column);
            }
        }

        for (int i = 0; i < columnsTemplate.size(); i++) {
            JSONObject jsonObject = columnsTemplate.getJSONObject(i);
            String title = jsonObject.getString("title");
            String dataIndex = jsonObject.getString("dataIndex");
            if (tableType.equals(FormConstant.LOGIC_TABLE_TYPE.SQL.getText())) {
                if (dataIndex.contains(".")) {
                    dataIndex = dataIndex.split("\\.")[1];
                }
            }
            if (columns.contains(dataIndex)) {
                map.put(dataIndex, title);
            }
        }

        return map;
    }

    private Workbook generateExcel(String name, Map<String, String> columnTitleMap, List<Map<String, Object>> dataList) {
        // 配置表头
        List<ExcelExportEntity> entityList = new ArrayList<>();
        columnTitleMap.forEach((key, title) -> entityList.add(new ExcelExportEntity(title, key)));

        // 配置数据
        return ExcelExportUtil.exportExcel(new ExportParams(name, "sheetName"), entityList, dataList);
    }

}
